

#ifndef SINGLECALL_H_
#define SINGLECALL_H_

#include <string>
#include <vector>

#include "os/OsDefs.h"
#include "tapi/sipXtapi.h"
#include "tapi/sipXtapiEvents.h"

#ifdef USE_LOADGEN_GUI
    #include <QThread>
    #include <QMutex>
#else
    #include <boost/utility.hpp>
    #include <boost/thread/thread.hpp>
    #include <boost/thread/xtime.hpp>
#endif // USE_LOADGEN_GUI


void SLEEP(int milliseconds);

/*extern "C" SIPXTAPI_API SIPX_RESULT sipxLineAdd(const SIPX_INST, const char*,SIPX_LINE*,SIPX_CONTACT_ID) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxLineRegister(const SIPX_LINE, const bool);
extern "C" SIPXTAPI_API SIPX_RESULT sipxCallCreate(const SIPX_INST, const SIPX_LINE, SIPX_CALL*) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxCallConnect(const SIPX_CALL, const char*, SIPX_CONTACT_ID, SIPX_VIDEO_DISPLAY* const) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxCallPlayFile(const SIPX_CALL, const char*, const bool, const bool) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxCallStartTone(const SIPX_CALL, const TONE_ID, const bool, const bool) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxCallStopTone(const SIPX_CALL) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxCallDestroy(SIPX_CALL&) ;
extern "C" SIPXTAPI_API SIPX_RESULT sipxLineRemove(SIPX_LINE) ;
extern "C" SIPXTAPI_API char* sipxEventToString(const SIPX_EVENT_CATEGORY, const void*, char*,size_t);
extern "C" SIPXTAPI_API SIPX_RESULT sipxEventListenerAdd(const SIPX_INST, SIPX_EVENT_CALLBACK_PROC, void *);
*/

#define MAX_RECORD_EVENTS       16
#define DEFAULT_SIPPORT         5060
#define MIN_RTP_PORT            6000
#define MAX_RTP_PORT            9000

//#define MAX_PAUSE_DURATION_MS (60*1000)


using std::string;
using std::vector;

enum LOADGEN_STATE 
{
    STATE_LOADED            = 10,
    STATE_RUNNING           = 30,
    STATE_INITIALIZING      = 40,
    STATE_CALLING           = 50,
    STATE_HANGED_UP         = 70,
    STATE_FORCED_HANGED_UP  = 80,
    STATE_UNINITIALIZING    = 90,
    STATE_STOPPED           = 100,
    STATE_STOPPED_ERROR     = 999
};

struct LOADGEN_SINGLECALL_STRUCT
{
    LOADGEN_STATE state;
    uint repeatCount;
    uint currentRepeat;
    uint myNumber;
    string filename;
};

class EventHistory;


class SingleCall :
    #ifdef USE_LOADGEN_GUI
        public QThread
    #else
        public boost::noncopyable
    #endif // USE_LOADGEN_GUI
{

#ifdef USE_LOADGEN_GUI
    Q_OBJECT

    signals :
        void updateListOfElements(int, bool);
        void updateThreadInfo( int number, int loop, QString state );
        void updateStatistics();

#endif // USE_LOADGEN_GUI


    private     :
        LOADGEN_STATE _state;

        SIPX_INST _sipXInst;
        SIPX_LINE _sipXLine;
        SIPX_CALL _sipXCall;

        SIPX_CALLSTATE_EVENT g_eRecordEvents[MAX_RECORD_EVENTS] ;    // List of last N events
        int g_iNextEvent ; 
        static uint _numberOfSingleCalls;
        static uint _numberOfStartedCalls;
        static uint badEndedCalls;

        uint _myNumber;
        string _filename;
        uint _currentRepeat;
        uint _repeatCount; 
        uint currentRtpPort;
        bool _playingFile;
        bool _doForceHangup;
#ifdef USE_LOADGEN_GUI
        static QMutex _mutex;
        static QMutex _cbMutex; // callback-mutex
#else
        static boost::mutex _mutex;
        static boost::mutex _cbMutex;
#endif // USE_LOADGEN_GUI


        EventHistory *_eventHistory;
        vector<string> _data;

    protected   :

        bool    createLine(string fromIdentity);
        bool    placeCall(string destinationUrl);
        bool    playFile(string filename);
        bool    playTones(string tones);
        bool    waitForSipXEvent(SIPX_CALLSTATE_MAJOR eMajor, int iTimeoutInSecs);

        bool    parseCommand(string command);
        string  findReplaceVariable(string token);
        void    clearSipXEvents();
        bool    eventCallBack(SIPX_EVENT_CATEGORY category, 
                              void* pInfo, 
                              void* pUserData);

        void tempLockInitializeResources();
        void tempLockUnInitializeResources();
        void addEventHistoryItem(string);
        void setState(const LOADGEN_STATE);
        void incrementBadEndedCalls();

        static uint rtpPort;

    public      :

        void run();
        void operator()();

        SingleCall( vector<string>,
                    int repeatCount,
                    string filename);

        ~SingleCall();

        static bool wrapper2EventCallBack(SIPX_EVENT_CATEGORY category, 
                   void* pInfo, 
                   void* pUserData);
        static void resetNumberOfSingleCalls();
        static int getNumberOfStartedCalls();
        static int getNumberOfBadEndedCalls();
        static int getPercentageGoodCalls();
        static string humanTranslateLoadgenState(LOADGEN_STATE);
        bool shutdownCall();
        bool isHangedUp();
        void forceHangUp();
        EventHistory* getEventHistory();
        void playAudio();
        int getMyNumber();
        int getCurrentRepeat();
        int getRepeatCount();
        string getFilename();
        LOADGEN_STATE getState();

};
#endif /*SINGLECALL_H_*/
